package org.yray.sip.rtp.server;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.util.StringUtils;


@Slf4j
public class UrtcpServer implements Runnable{


    private UrtcpServerHandler urtcpServerHandler;

    public UrtcpServer(UrtcpServerHandler urtcpServerHandler)
    {
        this.urtcpServerHandler=urtcpServerHandler;
    }

    public UrtcpServerHandler getUrtcpServerHandler() {
        return urtcpServerHandler;
    }

    @Override
    public void run() {
        String runIp=urtcpServerHandler.getSipServerContext().getRunIp();
        int runPort=urtcpServerHandler.getSipServerContext().getRunRtcpPort();
        boolean canEpoll=Epoll.isAvailable();
        log.info("is can epoll={}",canEpoll);
        Thread.currentThread().setName("UrtcpServer");
        EventLoopGroup bossGroup=canEpoll? new EpollEventLoopGroup():new NioEventLoopGroup();
        try{
            //通过NioDatagramChannel创建Channel，并设置Socket参数支持广播
            //UDP相对于TCP不需要在客户端和服务端建立实际的连接，因此不需要为连接（ChannelPipeline）设置handler
            Bootstrap b=new Bootstrap();
            ChannelInitializer channelInitializer=canEpoll?new EpollUrtcpChannelInitializer(urtcpServerHandler):new UrtcpChannelInitializer(urtcpServerHandler);
            b.group(bossGroup).channel(canEpoll? EpollDatagramChannel.class:NioDatagramChannel.class);
            if(canEpoll)
            {
                b.option(EpollChannelOption.SO_REUSEPORT, true);
            }
                // 设置读缓冲区为2K
            b.option(ChannelOption.SO_RCVBUF, 1024 * 1024)
                // 设置写缓冲区为2K
                .option(ChannelOption.SO_SNDBUF, 1024 * 1024)
                    // .option(ChannelOption.SO_BROADCAST, true)
                .handler(channelInitializer);


            ChannelFuture channelFuture= StringUtils.isEmpty(runIp)?b.bind(runPort).sync():b.bind(runIp,runPort).sync();

            urtcpServerHandler.setChannel(channelFuture.channel());
            log.info("UrtcpServer 启动成功 localAddress:[{}]",channelFuture.channel().localAddress());
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            log.error("UrtcpServer ip={},port={},启动错误:{}",runIp,runPort, ExceptionUtils.getStackTrace(e));
        }finally{
            bossGroup.shutdownGracefully();
        }
    }



}
